package com.chaodows.commons.dto.page;

import io.swagger.annotations.ApiModel;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

@EqualsAndHashCode(callSuper = true)
@XmlRootElement(name = "hash")
@Data
@NoArgsConstructor
@Builder()
@ApiModel("分页对象")
public class PageInfo<T> extends PaginationCondition implements Serializable {

    private static final long serialVersionUID = 4271378655516251360L;

    private int total;

    private int maxPage;

    private int fromPage;

    private int toPage;

    private List<T> items;

    public PageInfo(int page, int total, int pageSize, int maxPage, List<T> items) {
        super();
        super.setPage(page);
        this.total = total;
        super.setPageSize(pageSize);
        this.maxPage = maxPage;
        this.fromPage = 0;
        this.toPage = 0;
        this.items = items;
    }

    public PageInfo(List<T> items) {
        super();
        this.fromPage = 0;
        this.toPage = 0;
        this.items = items;
    }

    public List<T> getItems() {
        if (items == null) {
            this.items = new ArrayList<>();
        }
        return this.items;
    }

    public static <T> PageInfo<T> getInstance() {
        return new PageInfo<>();
    }

    public PageInfo(int page, int count, int pageSize, List<T> data) {
        pageSize = pageSize == 0 ? this.getPageSize() : pageSize;
        this.maxPage = count % pageSize == 0 ? count / pageSize : (count / pageSize + 1);
        super.setPage(page);
        this.total = count;
        super.setPageSize(pageSize);
        this.items = data;
    }

    public PageInfo<T> assemPaInfo(int page, int count, int pageSize, List<T> data) {
        pageSize = pageSize == 0 ? this.getPageSize() : pageSize;
        this.maxPage = count % pageSize == 0 ? count / pageSize : (count / pageSize + 1);
        super.setPage(page);
        this.total = count;
        super.setPageSize(pageSize);
        this.items = data;
        return this;
    }

    public static <T> PageInfo<T> creatPaging(PaginationCondition paging, int count, List<T> data) {

        return new PageInfo<>(paging.getPage(), count, paging.getPageSize(), data);
    }

    public static <T> PageInfo<T> creatPaging(int page, int pageSize, int count, List<T> data) {

        return new PageInfo<>(page, count, pageSize, data);
    }

    public static <T, R> PageInfo<R> transform(PageInfo<T> pageInfo, Function<T, R> function) {
        List<R> list = Optional.of(pageInfo.getItems()).orElse(Collections.emptyList()).stream().map(function)
                .collect(Collectors.toList());
        return new PageInfo<>(pageInfo.getPage(), pageInfo.getTotal(), pageInfo.getPageSize(), list);
    }

}
